//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension IoTDeviceAdvisor {
    // MARK: Enums

    public enum AuthenticationMethod: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case signatureVersion4 = "SignatureVersion4"
        case x509ClientCertificate = "X509ClientCertificate"
        public var description: String { return self.rawValue }
    }

    public enum Status: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case canceled = "CANCELED"
        case error = "ERROR"
        case fail = "FAIL"
        case pass = "PASS"
        case passWithWarnings = "PASS_WITH_WARNINGS"
        case pending = "PENDING"
        case running = "RUNNING"
        case stopped = "STOPPED"
        case stopping = "STOPPING"
        public var description: String { return self.rawValue }
    }

    public enum SuiteRunStatus: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case canceled = "CANCELED"
        case error = "ERROR"
        case fail = "FAIL"
        case pass = "PASS"
        case passWithWarnings = "PASS_WITH_WARNINGS"
        case pending = "PENDING"
        case running = "RUNNING"
        case stopped = "STOPPED"
        case stopping = "STOPPING"
        public var description: String { return self.rawValue }
    }

    public enum TestCaseScenarioStatus: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case canceled = "CANCELED"
        case error = "ERROR"
        case fail = "FAIL"
        case pass = "PASS"
        case passWithWarnings = "PASS_WITH_WARNINGS"
        case pending = "PENDING"
        case running = "RUNNING"
        case stopped = "STOPPED"
        case stopping = "STOPPING"
        public var description: String { return self.rawValue }
    }

    public enum TestCaseScenarioType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case advanced = "Advanced"
        case basic = "Basic"
        public var description: String { return self.rawValue }
    }

    public enum `Protocol`: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case mqttV311 = "MqttV3_1_1"
        case mqttV311Overwebsocket = "MqttV3_1_1_OverWebSocket"
        case mqttV5 = "MqttV5"
        case mqttV5Overwebsocket = "MqttV5_OverWebSocket"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct CreateSuiteDefinitionRequest: AWSEncodableShape {
        /// The client token for the test suite definition creation.  This token is used for tracking test suite definition creation  using retries and obtaining its status. This parameter is optional.
        public let clientToken: String?
        /// Creates a Device Advisor test suite with suite definition configuration.
        public let suiteDefinitionConfiguration: SuiteDefinitionConfiguration?
        /// The tags to be attached to the suite definition.
        public let tags: [String: String]?

        @inlinable
        public init(clientToken: String? = CreateSuiteDefinitionRequest.idempotencyToken(), suiteDefinitionConfiguration: SuiteDefinitionConfiguration? = nil, tags: [String: String]? = nil) {
            self.clientToken = clientToken
            self.suiteDefinitionConfiguration = suiteDefinitionConfiguration
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 64)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[\\u0021-\\u007E]+$")
            try self.suiteDefinitionConfiguration?.validate(name: "\(name).suiteDefinitionConfiguration")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, min: 1)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case clientToken = "clientToken"
            case suiteDefinitionConfiguration = "suiteDefinitionConfiguration"
            case tags = "tags"
        }
    }

    public struct CreateSuiteDefinitionResponse: AWSDecodableShape {
        /// The timestamp of when the test suite was created.
        public let createdAt: Date?
        /// The Amazon Resource Name (ARN) of the test suite.
        public let suiteDefinitionArn: String?
        /// The UUID of the test suite created.
        public let suiteDefinitionId: String?
        /// The suite definition name of the test suite. This is a required parameter.
        public let suiteDefinitionName: String?

        @inlinable
        public init(createdAt: Date? = nil, suiteDefinitionArn: String? = nil, suiteDefinitionId: String? = nil, suiteDefinitionName: String? = nil) {
            self.createdAt = createdAt
            self.suiteDefinitionArn = suiteDefinitionArn
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionName = suiteDefinitionName
        }

        private enum CodingKeys: String, CodingKey {
            case createdAt = "createdAt"
            case suiteDefinitionArn = "suiteDefinitionArn"
            case suiteDefinitionId = "suiteDefinitionId"
            case suiteDefinitionName = "suiteDefinitionName"
        }
    }

    public struct DeleteSuiteDefinitionRequest: AWSEncodableShape {
        /// Suite definition ID of the test suite to be deleted.
        public let suiteDefinitionId: String

        @inlinable
        public init(suiteDefinitionId: String) {
            self.suiteDefinitionId = suiteDefinitionId
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.suiteDefinitionId, key: "suiteDefinitionId")
        }

        public func validate(name: String) throws {
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, max: 36)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, min: 12)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteSuiteDefinitionResponse: AWSDecodableShape {
        public init() {}
    }

    public struct DeviceUnderTest: AWSEncodableShape & AWSDecodableShape {
        /// Lists device's certificate ARN.
        public let certificateArn: String?
        /// Lists device's role ARN.
        public let deviceRoleArn: String?
        /// Lists device's thing ARN.
        public let thingArn: String?

        @inlinable
        public init(certificateArn: String? = nil, deviceRoleArn: String? = nil, thingArn: String? = nil) {
            self.certificateArn = certificateArn
            self.deviceRoleArn = deviceRoleArn
            self.thingArn = thingArn
        }

        public func validate(name: String) throws {
            try self.validate(self.certificateArn, name: "certificateArn", parent: name, max: 2048)
            try self.validate(self.certificateArn, name: "certificateArn", parent: name, min: 20)
            try self.validate(self.deviceRoleArn, name: "deviceRoleArn", parent: name, max: 2048)
            try self.validate(self.deviceRoleArn, name: "deviceRoleArn", parent: name, min: 20)
            try self.validate(self.thingArn, name: "thingArn", parent: name, max: 2048)
            try self.validate(self.thingArn, name: "thingArn", parent: name, min: 20)
        }

        private enum CodingKeys: String, CodingKey {
            case certificateArn = "certificateArn"
            case deviceRoleArn = "deviceRoleArn"
            case thingArn = "thingArn"
        }
    }

    public struct GetEndpointRequest: AWSEncodableShape {
        /// The authentication method used during the device connection.
        public let authenticationMethod: AuthenticationMethod?
        /// The certificate ARN of the device. This is an optional parameter.
        public let certificateArn: String?
        /// The device role ARN of the device. This is an optional parameter.
        public let deviceRoleArn: String?
        /// The thing ARN of the device. This is an optional parameter.
        public let thingArn: String?

        @inlinable
        public init(authenticationMethod: AuthenticationMethod? = nil, certificateArn: String? = nil, deviceRoleArn: String? = nil, thingArn: String? = nil) {
            self.authenticationMethod = authenticationMethod
            self.certificateArn = certificateArn
            self.deviceRoleArn = deviceRoleArn
            self.thingArn = thingArn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.authenticationMethod, key: "authenticationMethod")
            request.encodeQuery(self.certificateArn, key: "certificateArn")
            request.encodeQuery(self.deviceRoleArn, key: "deviceRoleArn")
            request.encodeQuery(self.thingArn, key: "thingArn")
        }

        public func validate(name: String) throws {
            try self.validate(self.certificateArn, name: "certificateArn", parent: name, max: 2048)
            try self.validate(self.certificateArn, name: "certificateArn", parent: name, min: 20)
            try self.validate(self.deviceRoleArn, name: "deviceRoleArn", parent: name, max: 2048)
            try self.validate(self.deviceRoleArn, name: "deviceRoleArn", parent: name, min: 20)
            try self.validate(self.thingArn, name: "thingArn", parent: name, max: 2048)
            try self.validate(self.thingArn, name: "thingArn", parent: name, min: 20)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetEndpointResponse: AWSDecodableShape {
        /// The response of an Device Advisor endpoint.
        public let endpoint: String?

        @inlinable
        public init(endpoint: String? = nil) {
            self.endpoint = endpoint
        }

        private enum CodingKeys: String, CodingKey {
            case endpoint = "endpoint"
        }
    }

    public struct GetSuiteDefinitionRequest: AWSEncodableShape {
        /// Suite definition ID of the test suite to get.
        public let suiteDefinitionId: String
        /// Suite definition version of the test suite to get.
        public let suiteDefinitionVersion: String?

        @inlinable
        public init(suiteDefinitionId: String, suiteDefinitionVersion: String? = nil) {
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionVersion = suiteDefinitionVersion
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.suiteDefinitionId, key: "suiteDefinitionId")
            request.encodeQuery(self.suiteDefinitionVersion, key: "suiteDefinitionVersion")
        }

        public func validate(name: String) throws {
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, max: 36)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, min: 12)
            try self.validate(self.suiteDefinitionVersion, name: "suiteDefinitionVersion", parent: name, max: 255)
            try self.validate(self.suiteDefinitionVersion, name: "suiteDefinitionVersion", parent: name, min: 2)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetSuiteDefinitionResponse: AWSDecodableShape {
        /// Date (in Unix epoch time) when the suite definition was created.
        public let createdAt: Date?
        /// Date (in Unix epoch time) when the suite definition was last modified.
        public let lastModifiedAt: Date?
        /// Latest suite definition version of the suite definition.
        public let latestVersion: String?
        /// The ARN of the suite definition.
        public let suiteDefinitionArn: String?
        /// Suite configuration of the suite definition.
        public let suiteDefinitionConfiguration: SuiteDefinitionConfiguration?
        /// Suite definition ID of the suite definition.
        public let suiteDefinitionId: String?
        /// Suite definition version of the suite definition.
        public let suiteDefinitionVersion: String?
        /// Tags attached to the suite definition.
        public let tags: [String: String]?

        @inlinable
        public init(createdAt: Date? = nil, lastModifiedAt: Date? = nil, latestVersion: String? = nil, suiteDefinitionArn: String? = nil, suiteDefinitionConfiguration: SuiteDefinitionConfiguration? = nil, suiteDefinitionId: String? = nil, suiteDefinitionVersion: String? = nil, tags: [String: String]? = nil) {
            self.createdAt = createdAt
            self.lastModifiedAt = lastModifiedAt
            self.latestVersion = latestVersion
            self.suiteDefinitionArn = suiteDefinitionArn
            self.suiteDefinitionConfiguration = suiteDefinitionConfiguration
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionVersion = suiteDefinitionVersion
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case createdAt = "createdAt"
            case lastModifiedAt = "lastModifiedAt"
            case latestVersion = "latestVersion"
            case suiteDefinitionArn = "suiteDefinitionArn"
            case suiteDefinitionConfiguration = "suiteDefinitionConfiguration"
            case suiteDefinitionId = "suiteDefinitionId"
            case suiteDefinitionVersion = "suiteDefinitionVersion"
            case tags = "tags"
        }
    }

    public struct GetSuiteRunReportRequest: AWSEncodableShape {
        /// Suite definition ID of the test suite.
        public let suiteDefinitionId: String
        /// Suite run ID of the test suite run.
        public let suiteRunId: String

        @inlinable
        public init(suiteDefinitionId: String, suiteRunId: String) {
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteRunId = suiteRunId
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.suiteDefinitionId, key: "suiteDefinitionId")
            request.encodePath(self.suiteRunId, key: "suiteRunId")
        }

        public func validate(name: String) throws {
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, max: 36)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, min: 12)
            try self.validate(self.suiteRunId, name: "suiteRunId", parent: name, max: 36)
            try self.validate(self.suiteRunId, name: "suiteRunId", parent: name, min: 12)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetSuiteRunReportResponse: AWSDecodableShape {
        /// Download URL of the qualification report.
        public let qualificationReportDownloadUrl: String?

        @inlinable
        public init(qualificationReportDownloadUrl: String? = nil) {
            self.qualificationReportDownloadUrl = qualificationReportDownloadUrl
        }

        private enum CodingKeys: String, CodingKey {
            case qualificationReportDownloadUrl = "qualificationReportDownloadUrl"
        }
    }

    public struct GetSuiteRunRequest: AWSEncodableShape {
        /// Suite definition ID for the test suite run.
        public let suiteDefinitionId: String
        /// Suite run ID for the test suite run.
        public let suiteRunId: String

        @inlinable
        public init(suiteDefinitionId: String, suiteRunId: String) {
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteRunId = suiteRunId
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.suiteDefinitionId, key: "suiteDefinitionId")
            request.encodePath(self.suiteRunId, key: "suiteRunId")
        }

        public func validate(name: String) throws {
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, max: 36)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, min: 12)
            try self.validate(self.suiteRunId, name: "suiteRunId", parent: name, max: 36)
            try self.validate(self.suiteRunId, name: "suiteRunId", parent: name, min: 12)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetSuiteRunResponse: AWSDecodableShape {
        /// Date (in Unix epoch time) when the test suite run ended.
        public let endTime: Date?
        /// Error reason for any test suite run failure.
        public let errorReason: String?
        /// Date (in Unix epoch time) when the test suite run started.
        public let startTime: Date?
        /// Status for the test suite run.
        public let status: SuiteRunStatus?
        /// Suite definition ID for the test suite run.
        public let suiteDefinitionId: String?
        /// Suite definition version for the test suite run.
        public let suiteDefinitionVersion: String?
        /// The ARN of the suite run.
        public let suiteRunArn: String?
        /// Suite run configuration for the test suite run.
        public let suiteRunConfiguration: SuiteRunConfiguration?
        /// Suite run ID for the test suite run.
        public let suiteRunId: String?
        /// The tags attached to the suite run.
        public let tags: [String: String]?
        /// Test results for the test suite run.
        public let testResult: TestResult?

        @inlinable
        public init(endTime: Date? = nil, errorReason: String? = nil, startTime: Date? = nil, status: SuiteRunStatus? = nil, suiteDefinitionId: String? = nil, suiteDefinitionVersion: String? = nil, suiteRunArn: String? = nil, suiteRunConfiguration: SuiteRunConfiguration? = nil, suiteRunId: String? = nil, tags: [String: String]? = nil, testResult: TestResult? = nil) {
            self.endTime = endTime
            self.errorReason = errorReason
            self.startTime = startTime
            self.status = status
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionVersion = suiteDefinitionVersion
            self.suiteRunArn = suiteRunArn
            self.suiteRunConfiguration = suiteRunConfiguration
            self.suiteRunId = suiteRunId
            self.tags = tags
            self.testResult = testResult
        }

        private enum CodingKeys: String, CodingKey {
            case endTime = "endTime"
            case errorReason = "errorReason"
            case startTime = "startTime"
            case status = "status"
            case suiteDefinitionId = "suiteDefinitionId"
            case suiteDefinitionVersion = "suiteDefinitionVersion"
            case suiteRunArn = "suiteRunArn"
            case suiteRunConfiguration = "suiteRunConfiguration"
            case suiteRunId = "suiteRunId"
            case tags = "tags"
            case testResult = "testResult"
        }
    }

    public struct GroupResult: AWSDecodableShape {
        /// Group result ID.
        public let groupId: String?
        /// Group Result Name.
        public let groupName: String?
        /// Tests under Group Result.
        public let tests: [TestCaseRun]?

        @inlinable
        public init(groupId: String? = nil, groupName: String? = nil, tests: [TestCaseRun]? = nil) {
            self.groupId = groupId
            self.groupName = groupName
            self.tests = tests
        }

        private enum CodingKeys: String, CodingKey {
            case groupId = "groupId"
            case groupName = "groupName"
            case tests = "tests"
        }
    }

    public struct ListSuiteDefinitionsRequest: AWSEncodableShape {
        /// The maximum number of results to return at once.
        public let maxResults: Int?
        /// A token used to get the next set of results.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.maxResults, key: "maxResults")
            request.encodeQuery(self.nextToken, key: "nextToken")
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 50)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 2000)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListSuiteDefinitionsResponse: AWSDecodableShape {
        /// A token used to get the next set of results.
        public let nextToken: String?
        /// An array of objects that provide summaries of information about the suite definitions in the list.
        public let suiteDefinitionInformationList: [SuiteDefinitionInformation]?

        @inlinable
        public init(nextToken: String? = nil, suiteDefinitionInformationList: [SuiteDefinitionInformation]? = nil) {
            self.nextToken = nextToken
            self.suiteDefinitionInformationList = suiteDefinitionInformationList
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken = "nextToken"
            case suiteDefinitionInformationList = "suiteDefinitionInformationList"
        }
    }

    public struct ListSuiteRunsRequest: AWSEncodableShape {
        /// The maximum number of results to return at once.
        public let maxResults: Int?
        /// A token to retrieve the next set of results.
        public let nextToken: String?
        /// Lists the test suite runs of the specified test suite based on suite definition ID.
        public let suiteDefinitionId: String?
        /// Must be passed along with suiteDefinitionId. Lists the test suite runs of the specified test suite based on suite definition version.
        public let suiteDefinitionVersion: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil, suiteDefinitionId: String? = nil, suiteDefinitionVersion: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionVersion = suiteDefinitionVersion
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.maxResults, key: "maxResults")
            request.encodeQuery(self.nextToken, key: "nextToken")
            request.encodeQuery(self.suiteDefinitionId, key: "suiteDefinitionId")
            request.encodeQuery(self.suiteDefinitionVersion, key: "suiteDefinitionVersion")
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 50)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 2000)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, max: 36)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, min: 12)
            try self.validate(self.suiteDefinitionVersion, name: "suiteDefinitionVersion", parent: name, max: 255)
            try self.validate(self.suiteDefinitionVersion, name: "suiteDefinitionVersion", parent: name, min: 2)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListSuiteRunsResponse: AWSDecodableShape {
        /// A token to retrieve the next set of results.
        public let nextToken: String?
        /// An array of objects that provide summaries of information about the suite runs in the list.
        public let suiteRunsList: [SuiteRunInformation]?

        @inlinable
        public init(nextToken: String? = nil, suiteRunsList: [SuiteRunInformation]? = nil) {
            self.nextToken = nextToken
            self.suiteRunsList = suiteRunsList
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken = "nextToken"
            case suiteRunsList = "suiteRunsList"
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        /// The resource ARN of the IoT Device Advisor resource. This can be SuiteDefinition ARN or SuiteRun ARN.
        public let resourceArn: String

        @inlinable
        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// The tags attached to the IoT Device Advisor resource.
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct StartSuiteRunRequest: AWSEncodableShape {
        /// Suite definition ID of the test suite.
        public let suiteDefinitionId: String
        /// Suite definition version of the test suite.
        public let suiteDefinitionVersion: String?
        /// Suite run configuration.
        public let suiteRunConfiguration: SuiteRunConfiguration?
        /// The tags to be attached to the suite run.
        public let tags: [String: String]?

        @inlinable
        public init(suiteDefinitionId: String, suiteDefinitionVersion: String? = nil, suiteRunConfiguration: SuiteRunConfiguration? = nil, tags: [String: String]? = nil) {
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionVersion = suiteDefinitionVersion
            self.suiteRunConfiguration = suiteRunConfiguration
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.suiteDefinitionId, key: "suiteDefinitionId")
            try container.encodeIfPresent(self.suiteDefinitionVersion, forKey: .suiteDefinitionVersion)
            try container.encodeIfPresent(self.suiteRunConfiguration, forKey: .suiteRunConfiguration)
            try container.encodeIfPresent(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, max: 36)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, min: 12)
            try self.validate(self.suiteDefinitionVersion, name: "suiteDefinitionVersion", parent: name, max: 255)
            try self.validate(self.suiteDefinitionVersion, name: "suiteDefinitionVersion", parent: name, min: 2)
            try self.suiteRunConfiguration?.validate(name: "\(name).suiteRunConfiguration")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, min: 1)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case suiteDefinitionVersion = "suiteDefinitionVersion"
            case suiteRunConfiguration = "suiteRunConfiguration"
            case tags = "tags"
        }
    }

    public struct StartSuiteRunResponse: AWSDecodableShape {
        /// Starts a Device Advisor test suite run based on suite create time.
        public let createdAt: Date?
        /// The response of an Device Advisor test endpoint.
        public let endpoint: String?
        /// Amazon Resource Name (ARN) of the started suite run.
        public let suiteRunArn: String?
        /// Suite Run ID of the started suite run.
        public let suiteRunId: String?

        @inlinable
        public init(createdAt: Date? = nil, endpoint: String? = nil, suiteRunArn: String? = nil, suiteRunId: String? = nil) {
            self.createdAt = createdAt
            self.endpoint = endpoint
            self.suiteRunArn = suiteRunArn
            self.suiteRunId = suiteRunId
        }

        private enum CodingKeys: String, CodingKey {
            case createdAt = "createdAt"
            case endpoint = "endpoint"
            case suiteRunArn = "suiteRunArn"
            case suiteRunId = "suiteRunId"
        }
    }

    public struct StopSuiteRunRequest: AWSEncodableShape {
        /// Suite definition ID of the test suite run to be stopped.
        public let suiteDefinitionId: String
        /// Suite run ID of the test suite run to be stopped.
        public let suiteRunId: String

        @inlinable
        public init(suiteDefinitionId: String, suiteRunId: String) {
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteRunId = suiteRunId
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.suiteDefinitionId, key: "suiteDefinitionId")
            request.encodePath(self.suiteRunId, key: "suiteRunId")
        }

        public func validate(name: String) throws {
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, max: 36)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, min: 12)
            try self.validate(self.suiteRunId, name: "suiteRunId", parent: name, max: 36)
            try self.validate(self.suiteRunId, name: "suiteRunId", parent: name, min: 12)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct StopSuiteRunResponse: AWSDecodableShape {
        public init() {}
    }

    public struct SuiteDefinitionConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// Gets the device permission ARN. This is a required parameter.
        public let devicePermissionRoleArn: String?
        /// Gets the devices configured.
        public let devices: [DeviceUnderTest]?
        /// Gets the tests intended for qualification in a suite.
        public let intendedForQualification: Bool?
        /// Verifies if the test suite is a long duration test.
        public let isLongDurationTest: Bool?
        /// Sets the MQTT protocol that is configured in the suite definition.
        public let `protocol`: `Protocol`?
        /// Gets the test suite root group. This is a required parameter. For updating or creating the latest qualification suite,  if intendedForQualification is set to true,  rootGroup can be an empty string. If intendedForQualification is false,  rootGroup cannot be an empty string. If rootGroup is empty, and  intendedForQualification is set to true,  all the qualification tests are included, and the configuration is default.  For a qualification suite, the minimum length is 0, and the maximum is 2048.  For a  non-qualification suite, the minimum length is 1, and the maximum is 2048.
        public let rootGroup: String?
        /// Gets the suite definition name. This is a required parameter.
        public let suiteDefinitionName: String?

        @inlinable
        public init(devicePermissionRoleArn: String? = nil, devices: [DeviceUnderTest]? = nil, intendedForQualification: Bool? = nil, isLongDurationTest: Bool? = nil, protocol: `Protocol`? = nil, rootGroup: String? = nil, suiteDefinitionName: String? = nil) {
            self.devicePermissionRoleArn = devicePermissionRoleArn
            self.devices = devices
            self.intendedForQualification = intendedForQualification
            self.isLongDurationTest = isLongDurationTest
            self.`protocol` = `protocol`
            self.rootGroup = rootGroup
            self.suiteDefinitionName = suiteDefinitionName
        }

        public func validate(name: String) throws {
            try self.validate(self.devicePermissionRoleArn, name: "devicePermissionRoleArn", parent: name, max: 2048)
            try self.validate(self.devicePermissionRoleArn, name: "devicePermissionRoleArn", parent: name, min: 20)
            try self.devices?.forEach {
                try $0.validate(name: "\(name).devices[]")
            }
            try self.validate(self.devices, name: "devices", parent: name, max: 2)
            try self.validate(self.rootGroup, name: "rootGroup", parent: name, max: 2048)
            try self.validate(self.suiteDefinitionName, name: "suiteDefinitionName", parent: name, max: 256)
            try self.validate(self.suiteDefinitionName, name: "suiteDefinitionName", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case devicePermissionRoleArn = "devicePermissionRoleArn"
            case devices = "devices"
            case intendedForQualification = "intendedForQualification"
            case isLongDurationTest = "isLongDurationTest"
            case `protocol` = "protocol"
            case rootGroup = "rootGroup"
            case suiteDefinitionName = "suiteDefinitionName"
        }
    }

    public struct SuiteDefinitionInformation: AWSDecodableShape {
        /// Date (in Unix epoch time) when the test suite was created.
        public let createdAt: Date?
        /// Specifies the devices that are under test for the test suite.
        public let defaultDevices: [DeviceUnderTest]?
        /// Specifies if the test suite is intended for qualification.
        public let intendedForQualification: Bool?
        /// Verifies if the test suite is a long duration test.
        public let isLongDurationTest: Bool?
        /// Gets the MQTT protocol that is configured in the suite definition.
        public let `protocol`: `Protocol`?
        /// Suite definition ID of the test suite.
        public let suiteDefinitionId: String?
        /// Suite name of the test suite.
        public let suiteDefinitionName: String?

        @inlinable
        public init(createdAt: Date? = nil, defaultDevices: [DeviceUnderTest]? = nil, intendedForQualification: Bool? = nil, isLongDurationTest: Bool? = nil, protocol: `Protocol`? = nil, suiteDefinitionId: String? = nil, suiteDefinitionName: String? = nil) {
            self.createdAt = createdAt
            self.defaultDevices = defaultDevices
            self.intendedForQualification = intendedForQualification
            self.isLongDurationTest = isLongDurationTest
            self.`protocol` = `protocol`
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionName = suiteDefinitionName
        }

        private enum CodingKeys: String, CodingKey {
            case createdAt = "createdAt"
            case defaultDevices = "defaultDevices"
            case intendedForQualification = "intendedForQualification"
            case isLongDurationTest = "isLongDurationTest"
            case `protocol` = "protocol"
            case suiteDefinitionId = "suiteDefinitionId"
            case suiteDefinitionName = "suiteDefinitionName"
        }
    }

    public struct SuiteRunConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// TRUE if multiple test suites run in parallel.
        public let parallelRun: Bool?
        /// Sets the primary device for the test suite run. This requires a thing ARN or a certificate ARN.
        public let primaryDevice: DeviceUnderTest?
        /// Sets test case list.
        public let selectedTestList: [String]?

        @inlinable
        public init(parallelRun: Bool? = nil, primaryDevice: DeviceUnderTest? = nil, selectedTestList: [String]? = nil) {
            self.parallelRun = parallelRun
            self.primaryDevice = primaryDevice
            self.selectedTestList = selectedTestList
        }

        public func validate(name: String) throws {
            try self.primaryDevice?.validate(name: "\(name).primaryDevice")
            try self.selectedTestList?.forEach {
                try validate($0, name: "selectedTestList[]", parent: name, max: 36)
                try validate($0, name: "selectedTestList[]", parent: name, min: 12)
            }
            try self.validate(self.selectedTestList, name: "selectedTestList", parent: name, max: 100)
        }

        private enum CodingKeys: String, CodingKey {
            case parallelRun = "parallelRun"
            case primaryDevice = "primaryDevice"
            case selectedTestList = "selectedTestList"
        }
    }

    public struct SuiteRunInformation: AWSDecodableShape {
        /// Date (in Unix epoch time) when the suite run was created.
        public let createdAt: Date?
        /// Date (in Unix epoch time) when the suite run ended.
        public let endAt: Date?
        /// Number of test cases that failed in the suite run.
        public let failed: Int?
        /// Number of test cases that passed in the suite run.
        public let passed: Int?
        /// Date (in Unix epoch time) when the suite run was started.
        public let startedAt: Date?
        /// Status of the suite run.
        public let status: SuiteRunStatus?
        /// Suite definition ID of the suite run.
        public let suiteDefinitionId: String?
        /// Suite definition name of the suite run.
        public let suiteDefinitionName: String?
        /// Suite definition version of the suite run.
        public let suiteDefinitionVersion: String?
        /// Suite run ID of the suite run.
        public let suiteRunId: String?

        @inlinable
        public init(createdAt: Date? = nil, endAt: Date? = nil, failed: Int? = nil, passed: Int? = nil, startedAt: Date? = nil, status: SuiteRunStatus? = nil, suiteDefinitionId: String? = nil, suiteDefinitionName: String? = nil, suiteDefinitionVersion: String? = nil, suiteRunId: String? = nil) {
            self.createdAt = createdAt
            self.endAt = endAt
            self.failed = failed
            self.passed = passed
            self.startedAt = startedAt
            self.status = status
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionName = suiteDefinitionName
            self.suiteDefinitionVersion = suiteDefinitionVersion
            self.suiteRunId = suiteRunId
        }

        private enum CodingKeys: String, CodingKey {
            case createdAt = "createdAt"
            case endAt = "endAt"
            case failed = "failed"
            case passed = "passed"
            case startedAt = "startedAt"
            case status = "status"
            case suiteDefinitionId = "suiteDefinitionId"
            case suiteDefinitionName = "suiteDefinitionName"
            case suiteDefinitionVersion = "suiteDefinitionVersion"
            case suiteRunId = "suiteRunId"
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        /// The resource ARN of an IoT Device Advisor resource. This can be SuiteDefinition ARN or SuiteRun ARN.
        public let resourceArn: String
        /// The tags to be attached to the IoT Device Advisor resource.
        public let tags: [String: String]?

        @inlinable
        public init(resourceArn: String, tags: [String: String]? = nil) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
            try container.encodeIfPresent(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, min: 1)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct TestCaseRun: AWSDecodableShape {
        /// Provides test case run end time.
        public let endTime: Date?
        /// Provides test case run failure result.
        public let failure: String?
        /// Provides test case run log URL.
        public let logUrl: String?
        /// Provides test case run start time.
        public let startTime: Date?
        /// Provides the test case run status. Status is one of the following:    PASS: Test passed.    FAIL: Test failed.    PENDING: Test has not started running but is scheduled.    RUNNING: Test is running.    STOPPING: Test is performing cleanup steps. You will see this status only if you stop a suite run.    STOPPED Test is stopped. You will see this status only if you stop a suite run.    PASS_WITH_WARNINGS: Test passed with warnings.    ERORR: Test faced an error when running due to an internal issue.
        public let status: Status?
        /// Provides the test case run definition ID.
        public let testCaseDefinitionId: String?
        /// Provides the test case run definition name.
        public let testCaseDefinitionName: String?
        /// Provides the test case run ID.
        public let testCaseRunId: String?
        ///  Provides the test scenarios for the test case run.
        public let testScenarios: [TestCaseScenario]?
        /// Provides test case run warnings.
        public let warnings: String?

        @inlinable
        public init(endTime: Date? = nil, failure: String? = nil, logUrl: String? = nil, startTime: Date? = nil, status: Status? = nil, testCaseDefinitionId: String? = nil, testCaseDefinitionName: String? = nil, testCaseRunId: String? = nil, testScenarios: [TestCaseScenario]? = nil, warnings: String? = nil) {
            self.endTime = endTime
            self.failure = failure
            self.logUrl = logUrl
            self.startTime = startTime
            self.status = status
            self.testCaseDefinitionId = testCaseDefinitionId
            self.testCaseDefinitionName = testCaseDefinitionName
            self.testCaseRunId = testCaseRunId
            self.testScenarios = testScenarios
            self.warnings = warnings
        }

        private enum CodingKeys: String, CodingKey {
            case endTime = "endTime"
            case failure = "failure"
            case logUrl = "logUrl"
            case startTime = "startTime"
            case status = "status"
            case testCaseDefinitionId = "testCaseDefinitionId"
            case testCaseDefinitionName = "testCaseDefinitionName"
            case testCaseRunId = "testCaseRunId"
            case testScenarios = "testScenarios"
            case warnings = "warnings"
        }
    }

    public struct TestCaseScenario: AWSDecodableShape {
        /// Provides test case scenario failure result.
        public let failure: String?
        /// Provides the test case scenario status. Status is one of the following:    PASS: Test passed.    FAIL: Test failed.    PENDING: Test has not started running but is scheduled.    RUNNING: Test is running.    STOPPING: Test is performing cleanup steps. You will see this status only if you stop a suite run.    STOPPED Test is stopped. You will see this status only if you stop a suite run.    PASS_WITH_WARNINGS: Test passed with warnings.    ERORR: Test faced an error when running due to an internal issue.
        public let status: TestCaseScenarioStatus?
        /// Provides test case scenario system messages if any.
        public let systemMessage: String?
        /// Provides test case scenario ID.
        public let testCaseScenarioId: String?
        /// Provides test case scenario type. Type is one of the following:   Advanced   Basic
        public let testCaseScenarioType: TestCaseScenarioType?

        @inlinable
        public init(failure: String? = nil, status: TestCaseScenarioStatus? = nil, systemMessage: String? = nil, testCaseScenarioId: String? = nil, testCaseScenarioType: TestCaseScenarioType? = nil) {
            self.failure = failure
            self.status = status
            self.systemMessage = systemMessage
            self.testCaseScenarioId = testCaseScenarioId
            self.testCaseScenarioType = testCaseScenarioType
        }

        private enum CodingKeys: String, CodingKey {
            case failure = "failure"
            case status = "status"
            case systemMessage = "systemMessage"
            case testCaseScenarioId = "testCaseScenarioId"
            case testCaseScenarioType = "testCaseScenarioType"
        }
    }

    public struct TestResult: AWSDecodableShape {
        /// Show each group of test results.
        public let groups: [GroupResult]?

        @inlinable
        public init(groups: [GroupResult]? = nil) {
            self.groups = groups
        }

        private enum CodingKeys: String, CodingKey {
            case groups = "groups"
        }
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        /// The resource ARN of an IoT Device Advisor resource. This can be SuiteDefinition ARN or SuiteRun ARN.
        public let resourceArn: String
        /// List of tag keys to remove from the IoT Device Advisor resource.
        public let tagKeys: [String]?

        @inlinable
        public init(resourceArn: String, tagKeys: [String]? = nil) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
            request.encodeQuery(self.tagKeys, key: "tagKeys")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.tagKeys?.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 50)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateSuiteDefinitionRequest: AWSEncodableShape {
        /// Updates a Device Advisor test suite with suite definition configuration.
        public let suiteDefinitionConfiguration: SuiteDefinitionConfiguration?
        /// Suite definition ID of the test suite to be updated.
        public let suiteDefinitionId: String

        @inlinable
        public init(suiteDefinitionConfiguration: SuiteDefinitionConfiguration? = nil, suiteDefinitionId: String) {
            self.suiteDefinitionConfiguration = suiteDefinitionConfiguration
            self.suiteDefinitionId = suiteDefinitionId
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encodeIfPresent(self.suiteDefinitionConfiguration, forKey: .suiteDefinitionConfiguration)
            request.encodePath(self.suiteDefinitionId, key: "suiteDefinitionId")
        }

        public func validate(name: String) throws {
            try self.suiteDefinitionConfiguration?.validate(name: "\(name).suiteDefinitionConfiguration")
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, max: 36)
            try self.validate(self.suiteDefinitionId, name: "suiteDefinitionId", parent: name, min: 12)
        }

        private enum CodingKeys: String, CodingKey {
            case suiteDefinitionConfiguration = "suiteDefinitionConfiguration"
        }
    }

    public struct UpdateSuiteDefinitionResponse: AWSDecodableShape {
        /// Timestamp of when the test suite was created.
        public let createdAt: Date?
        /// Timestamp of when the test suite was updated.
        public let lastUpdatedAt: Date?
        /// Amazon Resource Name (ARN) of the updated test suite.
        public let suiteDefinitionArn: String?
        /// Suite definition ID of the updated test suite.
        public let suiteDefinitionId: String?
        /// Updates the suite definition name. This is a required parameter.
        public let suiteDefinitionName: String?
        /// Suite definition version of the updated test suite.
        public let suiteDefinitionVersion: String?

        @inlinable
        public init(createdAt: Date? = nil, lastUpdatedAt: Date? = nil, suiteDefinitionArn: String? = nil, suiteDefinitionId: String? = nil, suiteDefinitionName: String? = nil, suiteDefinitionVersion: String? = nil) {
            self.createdAt = createdAt
            self.lastUpdatedAt = lastUpdatedAt
            self.suiteDefinitionArn = suiteDefinitionArn
            self.suiteDefinitionId = suiteDefinitionId
            self.suiteDefinitionName = suiteDefinitionName
            self.suiteDefinitionVersion = suiteDefinitionVersion
        }

        private enum CodingKeys: String, CodingKey {
            case createdAt = "createdAt"
            case lastUpdatedAt = "lastUpdatedAt"
            case suiteDefinitionArn = "suiteDefinitionArn"
            case suiteDefinitionId = "suiteDefinitionId"
            case suiteDefinitionName = "suiteDefinitionName"
            case suiteDefinitionVersion = "suiteDefinitionVersion"
        }
    }
}

// MARK: - Errors

/// Error enum for IoTDeviceAdvisor
public struct IoTDeviceAdvisorErrorType: AWSErrorType {
    enum Code: String {
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize IoTDeviceAdvisor
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// Sends a Conflict Exception.
    public static var conflictException: Self { .init(.conflictException) }
    /// Sends an Internal Failure exception.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// Sends a Resource Not Found exception.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// Sends a validation exception.
    public static var validationException: Self { .init(.validationException) }
}

extension IoTDeviceAdvisorErrorType: Equatable {
    public static func == (lhs: IoTDeviceAdvisorErrorType, rhs: IoTDeviceAdvisorErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension IoTDeviceAdvisorErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
